<template>
  <el-card class="box-card">
    <div slot="header" class="clearfix">
      <span>更换头像</span>
    </div>
    <div>
      <!-- 图片，用来展示用户选择的头像 -->
      <img
        class="the_img"
        v-if="!avatar"
        src="../../assets/images/avatar.jpg"
        alt=""
      />
      <img class="the_img" v-else :src="avatar" alt="" />

      <!-- 按钮区域 -->
      <div class="btn-box">
        <input
          type="file"
          accept="image/*"
          style="display: none"
          ref="iptRef"
          @change="onFileChange"
        />
        <el-button type="primary" icon="el-icon-plus" @click="chooseImg"
          >选择图片</el-button
        >
        <el-button
          @click="uploadImg"
          type="success"
          icon="el-icon-upload"
          :disabled="avatar === ''"
          >上传头像</el-button
        >
      </div>
    </div>
  </el-card>
</template>

<script>
import { updtaeUserAvatarAPI } from '@/api'
import { mapActions } from 'vuex'
export default {
  name: 'UserAvatar',
  data() {
    return {
      avatar: '', // 保存图片链接/base64字符串
    }
  },
  methods: {
    ...mapActions(['initUserInfo']),

    // 目的：为了让 input[type=file] 标签，让他再用js代码来触发它的点击事件（导致它默认行为给一个文件选择窗口）
    // 原因：input[type=file] 他是原生标签，样式不太好改
    // 解决：移花接木
    // 选择图片->点击事件->让选择框出现，点击按钮触发input框的点击行为
    chooseImg() {
      this.$refs.iptRef.click()
    },
    // 在选择框中选择图片后触发的改变事件
    onFileChange(e) {
      // 拿到用户选择的文件列表（伪数组）
      // console.log(e.target.files)
      const files = e.target.files
      if (files.length === 0) {
        // files.length === 0，点了按钮，但是用户没有选择图片
        this.avatar = ''
      } else {
        // 选择了图片
        console.log(files[0])
        // 目标：选择图片文件，要给到img标签上做纯前端预览
        // 知识点：img标签的src值
        // 1. 只能是图片的 “链接地址”（外链http://开头，图片的相对路径）
        // 2. 或者是图片的base64字符串（而且字符串还必须是data:image/png,base64,图片转base64字符串）

        // 解决方案1：文件 -> 内存临时地址，使用`URL.createObjectURL`方法, 也可以把File类型文件, 转成一个Blob类型的纯前端本地的链接（这个地址只能在js内存里不能发给后台）
        // 语法： URL.createObjectURL(文件)
        // 返回值：内存临时地址
        // this.avatar = URL.createObjectURL(files[0])

        // 解决方案2：文件 -> base64字符串，使用**FileReader**来读取选择的前端文件, 转换为base64字符串, 给img标签渲染（此字符串可以发给后台）
        // 1. 创建 FileReader 对象
        const fr = new FileReader()
        // 2. 调用 readAsDataURL 函数，读取文件内容
        fr.readAsDataURL(files[0]) // 传入文件对象开始读
        // 3. 监听 fr 的 onload 事件
        // onload等待把文件读成base64字符串后会触发onload事件函数
        fr.onload = (e) => {
          // 4. 通过 e.target.result 获取到读取的结果，值是字符串（base64 格式的字符串）
          // e.target.result的值就是读完的结果
          this.avatar = e.target.result // 赋予变量，显示在img的src里
        }
      }
    },
    // 上传头像
    async uploadImg() {
      // 1.调接口，传递给后台并根据返回结果给用户提示
      const res = await updtaeUserAvatarAPI(this.avatar)
      console.log(res.data)
      // 2.请求失败
      if (res.data.code !== 0) return this.$message.error(res.data.message)
      // 3.提示用户
      this.$message.success(res.data.message)
      // 4.vuex中更新用户信息
      this.initUserInfo()
    },
  },
}
</script>

<style lang="scss" scoped>
.btn-box {
  margin-top: 10px;
}
.preview {
  object-fit: cover;
}
.the_img {
  width: 350px;
  height: 350px;
  border-radius: 50%;
}
</style>
